home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Source Code
/
Add-Ons
/
4D
/
ComboBox 1.1.1
/
src
/
ComboBoxArea.c
< prev
next >
Wrap
Text File
|
1996-02-23
|
32KB
|
1,142 lines
//---------------------------------------------------------------------------------------
//
// ComboBoxArea.c -- Source for ComboBox external area event handler
//
// Copyright ©1995-1996, Pensacola Christian College
//
// ======================================================================
// Change History
// ======================================================================
//
// 1.0 08/ /95 Steve Dwire
// Initial release
//
// 1.0.1 10/18/95 Steve Dwire
// Fix problem of losing Modified flag in AreaSelect()
//
// 1.1 a1 10/23/95 Steve Dwire
// Keep ComboBox from swallowing Enter key
//
// 10/25/95 Steve Dwire
// Fix problem of dead scroll bars resulting from more than one
// active list in the list window at one time (One list area seems
// to remain active from initialization, still. Needs to be fixed)
//
// 10/26/95 Steve Dwire
// Make closing the List call the script
//
// 1.1 11/17/95 Steve Dwire
// Because kCallTheScript can be passed only from a user event in
// the main process, I can't call the script directly when the user
// clicks in the list window to close it. So I'm making
// AreaHideList() post a unique keystroke (command-@, without shift)
// as an autoKey event. When I get that autokeystroke, I will pass
// back kCallTheScript. By making this an autoKey instead of a
// keyDown event, I allow a command-@ keystroke to be passed for
// those who have keyboards that will actually let them type one
// without using the shift key.
//
// 1.1.1a1 02/20/96 Steve Dwire
// Fix crash revealed with Charlie Rieman's "Less-Obnoxious Bus
// Error" control panel.
//
// 1.1.1a2 02/23/96 Steve Dwire
// Keep from swallowing Escape key and putting that ugly "dunno"
// box in the text field. Without this change, using Customiser
// to make Escape cancel a layout didn't work when a ComboBox
// was active.
//
//---------------------------------------------------------------------------------------
#include <Ext4D.h>
#include <QuickDraw.h>
#include <Palettes.h>
#include <ctype.h>
#include <stddef.h>
#include "ComboBoxMain.h"
#include "ComboBoxListMouseDown.h" // To pass on mousedown event to list
//---------------------------------------------------------------------------------
//
// FUNCTION: Area
//
//---------------------------------------------------------------------------------
//External area dispatcher
OSErr Area(EventRecord *event, Rect *bounds, UBYTE *name, AreaHnd *AreaData)
{
OSErr err;
err = noErr;
// Do we have an area data handle?
if(*AreaData)
switch(event->what)
{
//•Delete code handling events you do not wish to take
case kIdleEvt:
if ((**AreaData)->TextTEHnd && (**AreaData)->Flags.CanEdit)
TEIdle((**AreaData)->TextTEHnd);
break;
case kCursorEvt:
AreaCursor(*((AreaHnd*)AreaData), event);
//•Set the cursor to what it should be while over your area.
break;
case mouseDown:
//SysBeep(10);
AreaMouseDown(*((AreaHnd*)AreaData), event);
break;
case kScrollEvt:
case updateEvt:
//•Recalculate your bounding rectangle
AreaScrollRect(*((AreaHnd*)AreaData), bounds);
//•Redraw your area if need be
if(event->what == updateEvt)
AreaUpdate(*((AreaHnd*)AreaData), event);
break;
case keyDown:
//v1.1
// added the following lines:
AreaKeyDown(*((AreaHnd*)AreaData), event);
break;
// to separate autoKey from keyDown.
case autoKey:
//v1.1
// added the following lines:
if (((SBYTE)LoWord(event->message & charCodeMask) == '@') &&
(event->modifiers == cmdKey)) // this is our command-@ w/o shift keystroke
{
ParameterBlock block; // moved from AreaHideList
PackHnd PackDataHnd;
PackDataHnd = GetPackDataHnd();
block.fParam1 = (*PackDataHnd)->ListProcID; // moved from AreaHideList
CALL4D(kEX_FREEZE_PROCESS,&block); // moved from AreaHideList
event->message = kCallTheScript;
}
else
// to process the command-@ autokey
AreaKeyDown(*((AreaHnd*)AreaData), event);
break;
case kSelectEvt:
//•Delete this code if area cannot be selected
err = AreaSelect(*((AreaHnd*)AreaData), event);
break;
case kDeSelectEvt:
//•Delete this code if area cannot be selected
//•If cannot deselect yet, uncomment next line
//event->message = kZoneRefuse;
AreaDeselect(*((AreaHnd*)AreaData));
break;
//case kResizeEvt:
//•{Does this only happen for external windows?}
//break;
//case kTestPrintSizeEvt:
//•If this is a variable frame area, uncomment the next line
//event->message = kZoneVariableFrame;
//break;
//case kPrintSizeEvt:
// event->message = //*size of area left to print (in points)
// break;
//case kPrintBandEvt:
//•It's time to print your area
//break;
//case kUndoEvt:
//•User chose “Undo” from “Edit” menu.
//break;
//v1.1
// Moved kStructEvt outside if because AreaHnd is invalid for kStructEvt.
case kCutEvt:
//•User chose “Cut” from “Edit” menu.
AreaCut(*((AreaHnd*)AreaData));
break;
case kCopyEvt:
//•User chose “Copy” from “Edit” menu.
AreaCopy(*((AreaHnd*)AreaData));
break;
case kPasteEvt:
//•User chose “Paste” from “Edit” menu.
AreaPaste(*((AreaHnd*)AreaData));
break;
case kClearEvt:
//•User chose “Clear” from “Edit” menu.
AreaClear(*((AreaHnd*)AreaData));
break;
case kSelectAllEvt:
//•User chose “SelectAll” from “Edit” menu.
AreaSelectAll(*((AreaHnd*)AreaData));
break;
//case kInstallMenusEvt:
//•Install your area’s menus into the current menu bar.
//break;
//case kDeInstallMenusEvt:
//•Remove your area’s menus from the current menu bar.
//break;
//case kMenuSelectedEvt:
//•Someone chose one of your area’s menu items.
//•{Where do we get info on which item was chosen?}
//break;
//case kActivateMenusEvt:
//•{Not sure what this does.}
//event->message = kEventNotTaken;
//break;
//case kGrowBoxEvt:
//•If you need to limit the minimum size, uncomment the next lines
//event->modifiers = kNeedMinSize;
//event->message = /*Width & Height*/; //•{How do we encode this?}
//break;
case kTestEvt:
//•If area can be selected, uncomment next line.
if ((**AreaData)->Flags.Enabled)
event->message = kZoneCanBeSelected;
//•If area should be kept offscreen, uncomment next line.
//event->message = kUseOffScreen;
break;
default:
//we don't handle anything else.
event->message = kEventNotTaken;
break;
}
else
event->message = kEventNotTaken;
return err;
}
//---------------------------------------------------------------------------------
//
// FUNCTION: AreaCursor
//
//---------------------------------------------------------------------------------
void AreaCursor(AreaHnd AreaData, EventRecord* event)
{
switch(GetMouseLoc(AreaData,event))
{
case kInText:
if((*AreaData)->Flags.Active && (*AreaData)->Flags.CanEdit)
SetCursor(*GetCursor(iBeamCursor));
else
SetCursor(*GetCursor(GetResID('4BNX','CURS',1))); // standard arrow
break;
default:
SetCursor(*GetCursor(GetResID('4BNX','CURS',1))); // standard arrow
}
}
//---------------------------------------------------------------------------------
//
// FUNCTION: AreaMouseDown
//
//---------------------------------------------------------------------------------
void AreaMouseDown(AreaHnd AreaData, EventRecord* event)
{
MouseLocType MouseLoc;
ColorSpec OldFore, OldBack;
Boolean WaitMouse;
WaitMouse = false;
if((*AreaData)->Flags.Enabled)
{
if(TickCount() - (*AreaData)->ActivateTick > GetDblTime())
{
MouseLoc = GetMouseLoc(AreaData, event);
switch(MouseLoc)
{
case kInText:
SaveFore(&OldFore);
SaveBack(&OldBack);
PmForeColor((*AreaData)->TextFGColor);
PmBackColor((*AreaData)->TextBGColor);
if ((*AreaData)->Flags.CanEdit)
TEClick(event->where,(event->modifiers & shiftKey),(*AreaData)->TextTEHnd);
else if((*AreaData)->Flags.CanList)
{
AreaShowList(AreaData);
WaitMouse = true;
}
RestoreFore(&OldFore);
RestoreBack(&OldBack);
break;
case kInPICT:
if((*AreaData)->Flags.Open)
//v1.1
// removed the following lines from v1.1 a1:
//{
// event->message = kCallTheScript;
// because AreaHideList() takes care of it for us
AreaHideList(AreaData);
//v1.1
// removed the following line from v1.1 a1:
//}
// self-explanatory.
else if((*AreaData)->Flags.CanList)
{
AreaShowList(AreaData);
WaitMouse = true;
}
break;
default:
//v1.1
// removed the following lines from v1.1 a1:
//if ((*AreaData)->Flags.Open)
//{
// event->message = kCallTheScript;
// because AreaHideList() takes care of it for us
AreaHideList(AreaData);
//v1.1
// removed the following lines from v1.1 a1:
//}
//else
// because they're no longer necessary
event->message = kEventNotTaken;
}
}
else if ((*AreaData)->Flags.ListOnActivate)
WaitMouse = true;
if (WaitMouse)
{
ParameterBlock block;
Point MousePt;
EventRecord FakeEvent; // to pass mouse point to ListMouseDown()
WindowPtr ListWindow;
ListWindow = (*GetPackDataHnd())->ListWindow;
AreaUpdate(AreaData,event);
while (StillDown())
{
// If they ever wander over the list area, LClick() there.
CALL4D(kEX_YIELD_ABSOLUTE,&block);
CALL4D(kEX_YIELD_ABSOLUTE,&block); // Give the list process a chance
CALL4D(kEX_YIELD_ABSOLUTE,&block); // to update its list window
GetMouse(&MousePt);
LocalToGlobal(&MousePt);
if ((MousePt.h >= (*AreaData)->ListRect.left) &&
(MousePt.h <= (*AreaData)->ListRect.right - kScrollBarWidth) &&
(MousePt.v >= (*AreaData)->ListRect.top) &&
(MousePt.v <= (*AreaData)->ListRect.bottom))
{
FakeEvent.where = MousePt;
//v1.1
// removed the following line from v1.1 a1:
//FakeEvent.message = event->message;
// since ListMouseDown() no longer changes the message parameter to kCallTheScript
ListMouseDown (AreaData,&FakeEvent,ListWindow);
//v1.1
// removed the following line from v1.1 a1:
//event->message = FakeEvent.message;
// since ListMouseDown() no longer changes the message paramter to kCallTheScript
}
}
}
}
else
event->message = kEventNotTaken;
(*AreaData)->ActivateTick = 0;
}
//---------------------------------------------------------------------------------
//
// FUNCTION: AreaScrollRect
//
//---------------------------------------------------------------------------------
void AreaScrollRect(AreaHnd AreaDataHnd, Rect* AreaRect)
{
SLONG diffX, diffY;
AreaPtr AreaDataPtr;
HLock((Handle)AreaDataHnd);
AreaDataPtr = *AreaDataHnd;
diffX = AreaRect->left - AreaDataPtr->AreaRect.left;
diffY = AreaRect->top - AreaDataPtr->AreaRect.top;
if(diffX || diffY) //we moved
{
BlockMove(AreaRect, &(AreaDataPtr->AreaRect), sizeof(Rect));
OffsetRect(&(AreaDataPtr->PICTRect),diffX,diffY);
OffsetRect(&(AreaDataPtr->TextRect),diffX,diffY);
CalcListRect(AreaDataPtr);
CalcTextRect(AreaDataPtr);
}
HUnlock((Handle)AreaDataHnd);
if(diffX || diffY) //we moved
AreaHideList(AreaDataHnd);
}
//---------------------------------------------------------------------------------
//
// FUNCTION: AreaUpdate
//
//---------------------------------------------------------------------------------
void AreaUpdate(AreaHnd AreaData, EventRecord* event)
{
AreaPtr AreaDataPtr;
GrafPtr savePort;
TEHandle text;
Boolean IsColorQD;
PicHandle ThePICT;
ColorSpec OldFore, OldBack;
HLock((Handle)AreaData);
AreaDataPtr = *AreaData;
GetPort(&savePort);
IsColorQD = ((((CGrafPtr)savePort)->portVersion & 0xC000) == 0xC000);
if (IsColorQD)
{
if ((!AreaDataPtr->Flags.Enabled) && (AreaDataPtr->CPICTResDis != (-1)))
ThePICT = GetPicture(AreaDataPtr->CPICTResDis);
else
{
if (AreaDataPtr->Flags.Open)
ThePICT = GetPicture(AreaDataPtr->CPICTResDn);
else
ThePICT = GetPicture(AreaDataPtr->CPICTResUp);
}
}
else
{
if ((!AreaDataPtr->Flags.Enabled) && (AreaDataPtr->MPICTResDis != (-1)))
ThePICT = GetPicture(AreaDataPtr->MPICTResDis);
else
{
if (AreaDataPtr->Flags.Open)
ThePICT = GetPicture(AreaDataPtr->MPICTResDn);
else
ThePICT = GetPicture(AreaDataPtr->MPICTResUp);
}
}
DrawPicture(ThePICT,&AreaDataPtr->PICTRect);
SaveFore(&OldFore);
SaveBack(&OldBack);
PmForeColor(AreaDataPtr->TextFGColor);
PmBackColor(AreaDataPtr->TextBGColor);
EraseRect(&(AreaDataPtr->TextRect));
text = AreaDataPtr->TextTEHnd;
savePort = (*text)->inPort;
GetPort(&((*text)->inPort));
TEUpdate(&(AreaDataPtr->TextRect),text);
(*text)->inPort = savePort;
RestoreFore(&OldFore);
RestoreBack(&OldBack);
HUnlock((Handle)AreaData);
}
//---------------------------------------------------------------------------------
//
// FUNCTION: AreaKeyDown
//
//---------------------------------------------------------------------------------
void AreaKeyDown(AreaHnd AreaData, EventRecord* event)
{
SBYTE aChar;
TEHandle text;
ColorSpec OldFore, OldBack;
SWORD TextLength;
SBYTE *TextPtr;
aChar = (SBYTE)LoWord(event->message & charCodeMask);
if (event->modifiers & cmdKey)
event->message = kEventNotTaken;
else if ((*AreaData)->Flags.Enabled)
{
SaveFore(&OldFore);
SaveBack(&OldBack);
PmForeColor((*AreaData)->TextFGColor);
PmBackColor((*AreaData)->TextBGColor);
switch (aChar)
{
//v1.1 a1
//add the following three lines:
case (char)10: //Enter key
//v1.1.1a2
// add the following line:
case (char)27: //Escape key
//so we don't swallow the Escape key.
event->message = kEventNotTaken;
break;
//so we don't swallow the Enter key.
case '\r': //Return Key
event->message = kGoToNextField;
break;
case '\t': //Tab key
event->message = (event->modifiers & shiftKey)?kGoToPreviousField:kGoToNextField;
break;
case '\36': // Up arrow
case '\37': // Down arrow
{
ListHandle list;
TEHandle text;
Cell CurrCell;
Boolean OneWasSelected;
//move up in list
CurrCell.h = 0;
CurrCell.v = 0;
list = (*AreaData)->ListHnd;
text = (*AreaData)->TextTEHnd;
OneWasSelected = LGetSelect(true,&CurrCell,list);
if ((aChar == '\36') && ((CurrCell.v > 0) || (!OneWasSelected)))
{
CB_SetLstPos(AreaData,CurrCell.v+(!OneWasSelected));
(*AreaData)->Flags.Modified = true;
}
else if ((aChar == '\37') && (CurrCell.v < (*list)->dataBounds.bottom-1))
{
CB_SetLstPos(AreaData,CurrCell.v+1+OneWasSelected);
(*AreaData)->Flags.Modified = true;
}
if ((*AreaData)->Flags.ListOnKeystroke)
AreaShowList(AreaData);
(*AreaData)->KeyTick = 0;
break;
}
default:
{
text = (*AreaData)->TextTEHnd;
if((*AreaData)->Flags.CanEdit)
TEKey(aChar,text);
if((aChar != '\34') && (aChar != '\35'))
(*AreaData)->Flags.Modified = true;
else if ((*AreaData)->Flags.CanEdit == false)
event->message = (aChar == '\34')?kGoToPreviousField:kGoToNextField;
if((aChar != '\b') && (aChar != '\34') && (aChar != '\35'))
{
//Don't open it when user hits backspace, or the left or right arrow
if ((*AreaData)->Flags.ListOnKeystroke)
AreaShowList(AreaData);
if((*AreaData)->Flags.CanEdit)
{
TextLength = (*text)->teLength;
if(((*text)->selEnd == TextLength) && (TextLength > 0) && ((*AreaData)->Flags.CanFind))
{
//Search for it
HLock((*text)->hText);
TextPtr = *((*text)->hText);
if(AreaSearchList(TextPtr,TextLength,AreaData))
InvalRect(&(*AreaData)->AreaRect);
HUnlock((*text)->hText);
}
}
else
{
Handle SearchText;
SearchText = (Handle)(*AreaData)->SearchTextHandle;
if (TickCount() - (*AreaData)->KeyTick > GetDblTime())
(*AreaData)->SearchTextLength = 0;
if (++((*AreaData)->SearchTextLength) > (*AreaData)->SearchTextSize) // too big for Text Handle
{
(*AreaData)->SearchTextSize += 5;
SetHandleSize(SearchText, (*AreaData)->SearchTextSize);
}
(*SearchText)[(*AreaData)->SearchTextLength-1] = aChar;
HLock(SearchText);
if(AreaSearchList(*SearchText,(*AreaData)->SearchTextLength,AreaData))
InvalRect(&(*AreaData)->AreaRect);
HUnlock(SearchText);
(*AreaData)->KeyTick = TickCount();
}
}
}
}
RestoreFore(&OldFore);
RestoreBack(&OldBack);
}
else
event->message = kEventNotTaken;
}
//---------------------------------------------------------------------------------
//
// FUNCTION: AreaSearchList
//
//---------------------------------------------------------------------------------
Boolean AreaSearchList(SBYTE *TextPtr, SWORD TextLength, AreaHnd AreaDataHnd)
{
Cell SearchCell,OldCell;
register SWORD i,j;
register SWORD MaxCells;
Ptr CellDataPtr;
SWORD offset,len;
Boolean Found;
TEHandle text;
ListHandle list;
Found = false;
text = (*AreaDataHnd)->TextTEHnd;
list = (*AreaDataHnd)->ListHnd;
SearchCell.h = SearchCell.v = 0;
MaxCells = (*list)->dataBounds.bottom;
HLock((Handle)(*list)->cells);
CellDataPtr = *((*list)->cells);
for (i=0; i<MaxCells; i++) // Cells are zero-relative
{
SearchCell.v = i;
LGetCellDataLocation(&offset,&len,SearchCell,list);
if (TextLength <= len) // if it's too long, forget it!
{
Found = true; // assume so until we prove otherwise.
for (j=0; j<TextLength; j++) // character positions are also zero relative
{
if((TextPtr[j] & '_') != (CellDataPtr[offset+j] & '_'))
{
Found = false;
j = TextLength;
}
}
}
if (Found)
{
// Found it... let's display it.
if((*AreaDataHnd)->Flags.CanFill)
{
LGetCellDataLocation(&offset,&len,SearchCell,list);
TEDeactivate(text); // This is to eliminate the flicker of the insertion point.
TESetText(CellDataPtr+offset,len,text);
if((*AreaDataHnd)->Flags.CanEdit)
TESetSelect(TextLength,len,text);
else
TESetSelect(0,32767,text);
TEActivate(text);
}
// Set the Selection
OldCell.v = OldCell.h = 0;
while(LGetSelect(true,&OldCell,list))
LSetSelect(false,OldCell,list);
LSetSelect(true,SearchCell,list);
LAutoScroll(list);
i = MaxCells; // Stop looking; we found it!
}
}
HUnlock((Handle)(*list)->cells);
return Found;
}
//---------------------------------------------------------------------------------
//
// FUNCTION: AreaSelect
//
//---------------------------------------------------------------------------------
OSErr AreaSelect(AreaHnd AreaDataHnd, EventRecord *event)
{
AreaPtr AreaDataPtr;
OSErr err;
ColorSpec OldFore,OldBack;
err = noErr;
if((*AreaDataHnd)->Flags.Enabled)
{
HLock((Handle)AreaDataHnd);
AreaDataPtr = *AreaDataHnd;
//v1.0.1 changed following block:
//if((AreaDataPtr->Flags.ListOnActivate) &&
// (TickCount() - (*AreaDataHnd)->DeactivateTick > GetDblTime()))
//{
// err = AreaShowList(AreaDataHnd); // DROP DOWN THE LIST!!
//}
//to:
if(TickCount() - (*AreaDataHnd)->DeactivateTick > GetDblTime())
{
AreaDataPtr->Flags.Modified = false; // start w/ clean slate when selected
if(AreaDataPtr->Flags.ListOnActivate)
{
err = AreaShowList(AreaDataHnd); // DROP DOWN THE LIST!!
}
}
//because clicking a button causes deselect/select combination. Therefore,
//clicking a button made us think we were no longer modified, even when we
//were.
if (err == noErr)
{
if(AreaDataPtr->Flags.Visible)
{
SaveFore(&OldFore);
SaveBack(&OldBack);
PmForeColor(AreaDataPtr->TextFGColor);
PmBackColor(AreaDataPtr->TextBGColor);
TEActivate(AreaDataPtr->TextTEHnd);
AreaSelectAll(AreaDataHnd);
RestoreFore(&OldFore);
RestoreBack(&OldBack);
}
}
if(err == noErr)
{
AreaDataPtr->Flags.Active = true;
InvalRect(&(AreaDataPtr->AreaRect));
AreaDataPtr->ActivateTick = TickCount();
}
}
else
event->message = kGoToNextField;
//v1.0.1 moved following line into block above:
//AreaDataPtr->Flags.Modified = false; // start w/ clean slate when selected
HUnlock((Handle)AreaDataHnd);
return err;
}
//---------------------------------------------------------------------------------
//
// FUNCTION: AreaDeselect
//
//---------------------------------------------------------------------------------
void AreaDeselect(AreaHnd AreaDataHnd)
{
AreaPtr AreaDataPtr;
ColorSpec OldFore,OldBack;
HLock((Handle)AreaDataHnd);
AreaDataPtr = *AreaDataHnd;
SaveFore(&OldFore);
SaveBack(&OldBack);
PmForeColor((*AreaDataHnd)->TextFGColor);
PmBackColor((*AreaDataHnd)->TextBGColor);
TEDeactivate(AreaDataPtr->TextTEHnd);
RestoreFore(&OldFore);
RestoreBack(&OldBack);
if(AreaDataPtr->Flags.Open)
AreaHideList(AreaDataHnd); // CLOSE THE LIST BOX
AreaDataPtr->Flags.Active = false;
InvalRect(&(AreaDataPtr->AreaRect)); // redraw it
AreaDataPtr->Flags.Active = false;
AreaDataPtr->DeactivateTick = TickCount();
HUnlock((Handle)AreaDataHnd);
}
//---------------------------------------------------------------------------------
//
// FUNCTION: AreaCut
//
//---------------------------------------------------------------------------------
void AreaCut(AreaHnd AreaDataHnd)
{
AreaCopy(AreaDataHnd);
AreaClear(AreaDataHnd);
}
//---------------------------------------------------------------------------------
//
// FUNCTION: AreaCopy
//
//---------------------------------------------------------------------------------
void AreaCopy(AreaHnd AreaDataHnd)
{
TEHandle text;
XHANDLE chars;
SLONG selSize;
text = (*AreaDataHnd)->TextTEHnd;
chars = TEGetText(text);
if (chars)
{
selSize = (*text)->selEnd - (*text)->selStart;
if (selSize)
{
ZeroScrap();
HLock((Handle)chars);
PutScrap(selSize,'TEXT',(XPOINTER)&(*chars)[(*text)->selStart]);
HUnlock((Handle)chars);
}
}
}
//---------------------------------------------------------------------------------
//
// FUNCTION: AreaPaste
//
//---------------------------------------------------------------------------------
void AreaPaste(AreaHnd AreaDataHnd)
{
ColorSpec OldFore,OldBack;
XHANDLE chars;
SLONG offset,size;
if ((*AreaDataHnd)->Flags.CanEdit)
{
SaveFore(&OldFore);
SaveBack(&OldBack);
PmForeColor((*AreaDataHnd)->TextFGColor);
PmBackColor((*AreaDataHnd)->TextBGColor);
chars = (XHANDLE)NewHandle(0);
if (chars)
{
size = GetScrap(chars,'TEXT',&offset);
HLock((Handle)chars);
TESetText(*chars,size,(*AreaDataHnd)->TextTEHnd);
HUnlock((Handle)chars);
DisposeHandle((Handle)chars);
InvalRect(&((*AreaDataHnd)->AreaRect));
}
RestoreFore(&OldFore);
RestoreBack(&OldBack);
}
}
//---------------------------------------------------------------------------------
//
// FUNCTION: AreaClear
//
//---------------------------------------------------------------------------------
void AreaClear(AreaHnd AreaDataHnd)
{
ColorSpec OldFore,OldBack;
if((*AreaDataHnd)->Flags.CanEdit)
{
SaveFore(&OldFore);
SaveBack(&OldBack);
PmForeColor((*AreaDataHnd)->TextFGColor);
PmBackColor((*AreaDataHnd)->TextBGColor);
TEDelete((*AreaDataHnd)->TextTEHnd);
RestoreFore(&OldFore);
RestoreBack(&OldBack);
}
}
//---------------------------------------------------------------------------------
//
// FUNCTION: AreaSelectAll
//
//---------------------------------------------------------------------------------
void AreaSelectAll(AreaHnd AreaDataHnd)
{
ColorSpec OldFore,OldBack;
SaveFore(&OldFore);
SaveBack(&OldBack);
PmForeColor((*AreaDataHnd)->TextFGColor);
PmBackColor((*AreaDataHnd)->TextBGColor);
TESetSelect(0,32767,(*AreaDataHnd)->TextTEHnd);
RestoreFore(&OldFore);
RestoreBack(&OldBack);
}
//---------------------------------------------------------------------------------
//
// FUNCTION: AreaShowList
//
//---------------------------------------------------------------------------------
OSErr AreaShowList(AreaHnd AreaDataHnd)
{
Boolean wasOpen;
wasOpen = (*AreaDataHnd)->Flags.Open;
(*AreaDataHnd)->Flags.Open = true;
if(!wasOpen)
{
ParameterBlock block;
PackHnd PackDataHnd;
WindowPtr ListWindow;
GrafPtr savePort;
AreaPtr AreaDataPtr;
PackDataHnd = GetPackDataHnd();
(*PackDataHnd)->CurrAreaHnd = AreaDataHnd;
ListWindow = (*PackDataHnd)->ListWindow;
HLock((Handle)AreaDataHnd);
AreaDataPtr = *AreaDataHnd;
CalcListRect(AreaDataPtr);
MoveWindow(ListWindow,AreaDataPtr->ListRect.left,AreaDataPtr->ListRect.top,false);
SizeWindow(ListWindow,AreaDataPtr->ListRect.right-AreaDataPtr->ListRect.left,
AreaDataPtr->ListRect.bottom-AreaDataPtr->ListRect.top,
false);
GetPort(&savePort);
SetPort(ListWindow);
PmForeColor(AreaDataPtr->ListFGColor);
PmBackColor(AreaDataPtr->ListBGColor);
TextFont(AreaDataPtr->ListFont);
TextSize(AreaDataPtr->ListSize);
TextFace(AreaDataPtr->ListStyle);
SetPort(savePort);
InvalRect(&AreaDataPtr->AreaRect);
ShowWindow(ListWindow);
SelectWindow(ListWindow);
LAutoScroll(AreaDataPtr->ListHnd);
block.fParam1 = (*PackDataHnd)->ListProcID;
HUnlock((Handle)AreaDataHnd);
CALL4D(kEX_UNFREEZE,&block);
}
return noErr;
}
//---------------------------------------------------------------------------------
//
// FUNCTION: AreaHideList
//
//---------------------------------------------------------------------------------
void AreaHideList(AreaHnd AreaDataHnd)
{
Boolean wasOpen;
wasOpen = (*AreaDataHnd)->Flags.Open;
(*AreaDataHnd)->Flags.Open = false;
if(wasOpen)
{
//v1.1
// moved following line to autoKey event handler:
//ParameterBlock block;
// so that even ComboBoxListMouseDown can pause the process.
PackHnd PackDataHnd;
PackDataHnd = GetPackDataHnd();
//v1.1 a1
//added the following line:
LActivate(false, (*AreaDataHnd)->ListHnd);
//so that we don't have more than one active list at a time. This was
//causing dead (or partially-dead) scroll bars.
HideWindow((*PackDataHnd)->ListWindow);
MoveWindow((*PackDataHnd)->ListWindow,0,0,false);
SizeWindow((*PackDataHnd)->ListWindow,1,1,false);
InvalRect(&(*AreaDataHnd)->AreaRect);
//v1.1
// added the following line:
PostKey((unsigned long)'@', (unsigned long) cmdKey,true);
// to cause a user event that triggers kCallTheScript
//v1.1
// moved the following 2 lines to autoKey event handler:
//block.fParam1 = (*PackDataHnd)->ListProcID;
//CALL4D(kEX_FREEZE_PROCESS,&block);
// so that even ComboBoxListMouseDown can pause the process.
}
}
//---------------------------------------------------------------------------------
//
// FUNCTION: GetMouseLoc
//
//---------------------------------------------------------------------------------
MouseLocType GetMouseLoc(AreaHnd AreaData, EventRecord* event)
{
if(PtInRect(event->where, &((*AreaData)->TextRect)))
return kInText;
else if(PtInRect(event->where, &((*AreaData)->PICTRect)))
return kInPICT;
else
return kOutside;
}
//---------------------------------------------------------------------------------
//
// FUNCTION: CalcTextRect
//
//---------------------------------------------------------------------------------
void CalcTextRect (AreaPtr AreaDataPtr)
{
int TopBorder,RightBorder;
FontInfo FntInfo;
GrafPtr CurrGrafPort;
TEHandle text;
TopBorder = AreaDataPtr->PixLead;
RightBorder = AreaDataPtr->PixGap
+ AreaDataPtr->PICTRect.right
- AreaDataPtr->PICTRect.left;
CurrGrafPort = AreaDataPtr->AreaGrafPort;
TextFont(AreaDataPtr->TextFont);
TextSize(AreaDataPtr->TextSize);
TextFace((Style)(Byte)(AreaDataPtr->TextStyle));
GetFontInfo(&(FntInfo));
TextFont(CurrGrafPort->txFont);
TextSize(CurrGrafPort->txSize);
TextFace(CurrGrafPort->txFace);
AreaDataPtr->TextRect.top = AreaDataPtr->AreaRect.top + TopBorder;
AreaDataPtr->TextRect.left = AreaDataPtr->AreaRect.left;
AreaDataPtr->TextRect.bottom = AreaDataPtr->TextRect.top
+ FntInfo.ascent
+ FntInfo.descent;
AreaDataPtr->TextRect.right = AreaDataPtr->AreaRect.right - RightBorder;
// make sure the text rectangle is inside the area rectangle
SectRect(&(AreaDataPtr->TextRect),&(AreaDataPtr->AreaRect),&(AreaDataPtr->TextRect));
text = AreaDataPtr->TextTEHnd;
//v1.1.1
// added the following two lines:
if (text)
{
// because CalcTextRect is called before AreaDataPtr->TextTEHnd is created
BlockMove(&(AreaDataPtr->TextRect),&((*text)->destRect),sizeof(Rect));
BlockMove(&(AreaDataPtr->TextRect),&((*text)->viewRect),sizeof(Rect));
//v1.1.1
// added the following line:
}
// to close the above block
}
//---------------------------------------------------------------------------------
//
// FUNCTION: CalcListRect
//
//---------------------------------------------------------------------------------
void CalcListRect(AreaPtr AreaDataPtr)
{
GrafPtr CurrGrafPort;
FontInfo FntInfo;
SWORD CurrFont,CurrSize,CurrFace,RectHeight;
GDHandle screenGD;
Rect screenRect,GlobalAreaRect;
Point GlobalTopLeft;
// determine the height of a row in the list
GetPort(&CurrGrafPort);
CurrFont = CurrGrafPort->txFont;
CurrSize = CurrGrafPort->txSize;
CurrFace = CurrGrafPort->txFace;
TextFont(AreaDataPtr->ListFont);
TextSize(AreaDataPtr->ListSize);
TextFace(AreaDataPtr->ListStyle);
GetFontInfo(&FntInfo);
TextFont(CurrFont);
TextSize(CurrSize);
TextFace(CurrFace);
// calculate the height of the list rectangle
RectHeight = (FntInfo.ascent + FntInfo.descent + FntInfo.leading) * AreaDataPtr->ListRows;
// find bounding rectangle of the main screen
screenGD = GetMainDevice();
BlockMove(&((*screenGD)->gdRect),&screenRect,sizeof(Rect));
// determine global coordinates of area rectangle
BlockMove(&(AreaDataPtr->AreaRect),&GlobalAreaRect,sizeof(Rect));
GlobalAreaRect.left += AreaDataPtr->LeftGap;
GlobalAreaRect.right -= AreaDataPtr->RightGap;
GlobalTopLeft.v = GlobalAreaRect.top;
GlobalTopLeft.h = GlobalAreaRect.left;
SetPort(AreaDataPtr->AreaGrafPort);
LocalToGlobal(&GlobalTopLeft);
SetPort(CurrGrafPort);
OffsetRect(&GlobalAreaRect, GlobalTopLeft.h - GlobalAreaRect.left,
GlobalTopLeft.v + AreaDataPtr->TopGap - GlobalAreaRect.top);
// position list box just below the area's rectangle
AreaDataPtr->ListRect.top = GlobalAreaRect.bottom;
AreaDataPtr->ListRect.left = GlobalAreaRect.left;
AreaDataPtr->ListRect.right = GlobalAreaRect.right;
AreaDataPtr->ListRect.bottom = AreaDataPtr->ListRect.top + RectHeight;
if(AreaDataPtr->ListRect.bottom > screenRect.bottom)
{
// the list box goes below the bottom of the screen, so put it above the area rectangle
OffsetRect(&(AreaDataPtr->ListRect),0,
-(AreaDataPtr->TopGap+2+RectHeight+(GlobalAreaRect.bottom-GlobalAreaRect.top)));
}
if(AreaDataPtr->ListHnd)
{
(*(AreaDataPtr->ListHnd))->indent.v = FntInfo.ascent;
(*(AreaDataPtr->ListHnd))->cellSize.v = FntInfo.ascent + FntInfo.descent + FntInfo.leading;
LSize(AreaDataPtr->ListRect.right - AreaDataPtr->ListRect.left - kScrollBarWidth,
AreaDataPtr->ListRect.bottom - AreaDataPtr->ListRect.top,AreaDataPtr->ListHnd);
}
}
//---------------------------------------------------------------------------------
//
// FUNCTION: RedrawList
//
//---------------------------------------------------------------------------------
void RedrawList(AreaPtr AreaDataPtr)
{
if(AreaDataPtr->Flags.Open)
{
GrafPtr savePort;
PackHnd PackDataHnd;
GetPort(&savePort);
PackDataHnd = GetPackDataHnd();
SetPort((*PackDataHnd)->ListWindow);
InvalRect(&((*PackDataHnd)->ListWindow->portRect));
SetPort(savePort);
}
}